<?php

declare(strict_types=1);

namespace WebmanGrpc\Client;

use Grpc\Channel;
use Grpc\ChannelCredentials;
use Google\Protobuf\Internal\Message;
use WebmanGrpc\Grpc;
use WebmanGrpc\Pool\ConnectionPool;
use WebmanGrpc\Serialization\SerializationOptimizer;
use WebmanGrpc\PerformanceMonitor;

/**
 * gRPC客户端类
 * 
 * 提供便捷的gRPC客户端调用接口，支持：
 * - 简单调用：标准的请求-响应模式
 * - 流式调用：服务器流式响应
 * - 连接池管理：复用连接，提高性能
 * - 自动重试：失败后自动重试，支持指数退避
 * - 负载均衡：通过连接池支持多地址负载均衡
 * 
 * 主要功能：
 * 1. 管理gRPC连接的生命周期
 * 2. 提供简单易用的调用接口
 * 3. 自动处理序列化和反序列化
 * 4. 集成性能监控和统计
 * 5. 支持连接预热和优化
 * 
 * 使用场景：
 * - 微服务间通信
 * - 高性能API调用
 * - 流式数据处理
 * - 分布式系统集成
 * 
 * 使用示例：
 * ```php
 * // 创建客户端
 * $client = new GrpcClient('localhost:50051', [
 *     'timeout' => 5000,
 *     'retry' => 3,
 * ]);
 * 
 * // 调用服务
 * $request = new HelloRequest();
 * $request->setName('World');
 * 
 * $response = $client->call('helloworld.Greeter', 'SayHello', $request);
 * echo $response->getMessage();
 * 
 * // 流式调用
 * foreach ($client->stream('helloworld.Greeter', 'SayHelloStream', $request) as $response) {
 *     echo $response->getMessage() . "\n";
 * }
 * 
 * // 关闭客户端
 * $client->close();
 * ```
 * 
 * @author Webman gRPC Team
 * @version 1.1.0
 * @since 1.0.0
 */
class GrpcClient
{
    /**
     * gRPC通道
     * 
     * 用于与gRPC服务器通信的底层通道对象。通道是客户端与服务器之间的连接，
     * 管理网络通信、序列化/反序列化和其他底层细节。
     * 
     * @var Channel
     */
    protected Channel $channel;
    
    /**
     * 服务地址
     * 
     * gRPC服务器的地址，格式为"host:port"，例如"localhost:50051"。
     * 此地址用于建立连接和进行连接池管理。
     * 
     * @var string
     */
    protected string $address;
    
    /**
     * 客户端选项
     * 
     * 包含客户端配置的关联数组，包括：
     * - timeout: 请求超时时间（毫秒），默认5000
     * - retry: 重试次数，默认3
     * - backoff: 退避配置，包含initial（初始延迟）、multiplier（倍数）、max（最大延迟）
     * - credentials: 认证凭据配置
     * - serialization: 序列化配置
     * - stream_processor: 流处理器配置
     * 
     * @var array
     */
    protected array $options;
    
    /**
     * 连接池管理器
     * 
     * 用于管理gRPC连接的连接池实例。连接池可以复用连接，减少建立连接的开销，
     * 提高性能。它还支持连接预热、健康检查和负载均衡。
     * 
     * @var ConnectionPool
     */
    protected ConnectionPool $connectionPool;
    
    /**
     * 构造函数
     * 
     * 创建一个新的gRPC客户端实例，初始化连接和配置。
     * 构造函数会合并默认配置和用户提供的选项，初始化序列化优化器，
     * 并从连接池获取或创建连接。
     * 
     * 初始化流程：
     * 1. 保存服务地址
     * 2. 合并配置选项（默认配置 + 用户配置）
     * 3. 获取连接池管理器实例
     * 4. 初始化序列化优化器
     * 5. 从连接池获取或创建连接
     * 
     * 使用场景：
     * - 创建与gRPC服务的连接
     * - 初始化客户端配置
     * - 准备进行gRPC调用
     * 
     * 使用示例：
     * ```php
     * // 使用默认配置
     * $client = new GrpcClient('localhost:50051');
     * 
     * // 使用自定义配置
     * $client = new GrpcClient('localhost:50051', [
     *     'timeout' => 10000,
     *     'retry' => 5,
     *     'credentials' => [
     *         'ssl' => true,
     *         'pem_file' => '/path/to/cert.pem'
     *     ]
     * ]);
     * ```
     * 
     * @param string $address 服务地址，格式为"host:port"，例如"localhost:50051"
     * @param array $options 客户端选项，包含超时、重试、认证等配置
     */
    public function __construct(string $address, array $options = [])
    {
        $this->address = $address;
        $this->options = array_merge(Grpc::getConfig('client', []), $options);
        
        // 获取连接池管理器
        $this->connectionPool = ConnectionPool::getInstance();
        
        // 初始化序列化优化器
        SerializationOptimizer::initialize($this->options['serialization'] ?? []);
        
        // 创建或获取连接
        $this->channel = $this->connectionPool->getConnection($address, $this->options);
    }
    
    /**
     * 连接预热
     * 
     * 预先建立与多个gRPC服务器的连接，以减少首次调用的延迟。
     * 连接预热可以显著提高应用启动后的首次请求性能，特别适用于
     * 高并发场景和对延迟敏感的应用。
     * 
     * 预热过程：
     * 1. 获取连接池管理器
     * 2. 对每个地址建立连接
     * 3. 将连接放入连接池
     * 
     * 使用场景：
     * - 应用启动时预热连接
     * - 高并发场景提前准备连接
     * - 减少首次请求延迟
     * 
     * 使用示例：
     * ```php
     * // 预热多个服务地址
     * GrpcClient::warmUpConnections([
     *     'localhost:50051',
     *     'localhost:50052',
     *     'localhost:50053'
     * ], [
     *     'timeout' => 5000,
     *     'credentials' => ['ssl' => true]
     * ]);
     * ```
     * 
     * @param array $addresses 服务地址列表，每个地址格式为"host:port"
     * @param array $options 连接选项，包含超时、认证等配置
     * @return void
     */
    public static function warmUpConnections(array $addresses, array $options = []): void
    {
        $connectionPool = ConnectionPool::getInstance();
        $connectionPool->warmUp($addresses, $options);
    }
    
    /**
     * 调用gRPC服务
     * 
     * 执行标准的请求-响应模式gRPC调用。此方法会构建完整的方法名，
     * 设置超时，执行性能监控，并在失败时自动重试。
     * 
     * 调用流程：
     * 1. 构建完整方法名（/服务名/方法名）
     * 2. 合并选项和设置超时
     * 3. 开始性能监控
     * 4. 执行调用（带重试机制）
     * 5. 记录请求结果（成功或失败）
     * 6. 返回响应或抛出异常
     * 
     * 性能监控：
     * - 记录请求开始时间
     * - 计算请求大小
     * - 计算响应大小
     * - 记录请求结果和错误信息
     * 
     * 使用场景：
     * - 标准的gRPC服务调用
     * - 需要性能监控的请求
     * - 需要自动重试的请求
     * 
     * 使用示例：
     * ```php
     * // 基本调用
     * $request = new HelloRequest();
     * $request->setName('World');
     * 
     * $response = $client->call('helloworld.Greeter', 'SayHello', $request);
     * echo $response->getMessage();
     * 
     * // 带元数据的调用
     * $response = $client->call('helloworld.Greeter', 'SayHello', $request, [
     *     'authorization' => 'Bearer token123',
     *     'request-id' => uniqid()
     * ]);
     * 
     * // 带自定义选项的调用
     * $response = $client->call('helloworld.Greeter', 'SayHello', $request, [], [
     *     'timeout' => 10000,
     *     'retry' => 5
     * ]);
     * ```
     * 
     * @param string $service 服务名称，例如"helloworld.Greeter"
     * @param string $method 方法名，例如"SayHello"
     * @param Message $request 请求消息，必须是Protobuf消息对象
     * @param array $metadata 元数据，键值对数组，用于传递认证、追踪等信息
     * @param array $options 调用选项，包含超时、重试等配置
     * @return Message 响应消息，Protobuf消息对象
     * @throws \RuntimeException 当调用失败时抛出异常
     * @throws \Exception 其他可能的异常
     */
    public function call(string $service, string $method, Message $request, array $metadata = [], array $options = []): Message
    {
        // 构建完整方法名
        $fullMethod = "/{$service}/{$method}";
        
        // 合并选项
        $callOptions = array_merge($this->options, $options);
        
        // 设置超时
        $deadline = time() + $callOptions['timeout'];
        
        // 获取性能监控器实例
        $performanceMonitor = PerformanceMonitor::getInstance();
        
        // 开始性能监控
        $requestId = $performanceMonitor->startRequest($method, $service, $metadata);
        
        try {
            // 执行调用
            $response = $this->callWithRetry($fullMethod, $request, $metadata, $callOptions, $deadline);
            
            // 记录请求成功
            $requestSize = $request ? $request->ByteSize() : 0;
            $responseSize = $response ? $response->ByteSize() : 0;
            $performanceMonitor->endRequest($requestId, true, $requestSize, $responseSize);
            
            return $response;
        } catch (\Exception $e) {
            // 记录请求失败
            $requestSize = $request ? $request->ByteSize() : 0;
            $performanceMonitor->endRequest($requestId, false, $requestSize, 0, $e->getMessage());
            
            throw $e;
        }
    }
    
    /**
     * 流式调用
     * 
     * 执行服务器流式响应的gRPC调用。此方法返回一个生成器，
     * 可以逐个处理服务器返回的响应消息。支持可选的流处理器
     * 来优化流式数据的处理。
     * 
     * 流式调用流程：
     * 1. 构建完整方法名
     * 2. 合并选项和设置超时
     * 3. 创建流式调用
     * 4. 处理响应流（常规或使用流处理器）
     * 5. 检查调用状态
     * 
     * 流处理器：
     * 当启用流处理器时，可以批量处理响应消息，提高处理效率。
     * 流处理器支持配置批大小、处理间隔等参数。
     * 
     * 使用场景：
     * - 处理大量数据的流式响应
     * - 实时数据流处理
     * - 需要逐步处理结果的场景
     * 
     * 使用示例：
     * ```php
     * // 基本流式调用
     * $request = new StreamRequest();
     * $request->setQuery('data');
     * 
     * foreach ($client->stream('data.Service', 'GetDataStream', $request) as $response) {
     *     echo $response->getData() . "\n";
     * }
     * 
     * // 使用流处理器
     * foreach ($client->stream('data.Service', 'GetDataStream', $request, [], [
     *     'stream_processor' => [
     *         'enabled' => true,
     *         'batch_size' => 10,
     *         'interval' => 100
     *     ]
     * ]) as $response) {
     *     echo $response->getData() . "\n";
     * }
     * ```
     * 
     * @param string $service 服务名称，例如"data.Service"
     * @param string $method 方法名，例如"GetDataStream"
     * @param Message $request 请求消息，必须是Protobuf消息对象
     * @param array $metadata 元数据，键值对数组，用于传递认证、追踪等信息
     * @param array $options 调用选项，包含超时、流处理器等配置
     * @return \Generator 响应流生成器，逐个产生响应消息
     * @throws \RuntimeException 当流式调用失败时抛出异常
     */
    public function stream(string $service, string $method, Message $request, array $metadata = [], array $options = []): \Generator
    {
        // 构建完整方法名
        $fullMethod = "/{$service}/{$method}";
        
        // 合并选项
        $callOptions = array_merge($this->options, $options);
        
        // 设置超时
        $deadline = time() + $callOptions['timeout'];
        
        // 创建流式调用
        $call = $this->channel->call($fullMethod, $request, $metadata, $callOptions);
        
        // 如果启用了流式处理器，使用它来处理响应
        if (isset($callOptions['stream_processor']) && $callOptions['stream_processor']['enabled']) {
            $streamProcessor = new \WebmanGrpc\Stream\StreamProcessor($callOptions['stream_processor']);
            
            $generator = function() use ($call) {
                foreach ($call->responses() as $response) {
                    yield $response;
                }
            };
            
            $processor = function($batch) {
                foreach ($batch as $response) {
                    yield $response;
                }
            };
            
            foreach ($streamProcessor->processMessageStream($generator(), $processor) as $response) {
                yield $response;
            }
        } else {
            // 常规流式处理
            foreach ($call->responses() as $response) {
                yield $response;
            }
        }
        
        // 获取状态
        $status = $call->getStatus();
        if ($status->code !== \Grpc\STATUS_OK) {
            throw new \RuntimeException("gRPC call failed: [{$status->code}] {$status->details}");
        }
    }
    
    /**
     * 带重试的调用
     * 
     * 执行gRPC调用，并在失败时根据配置进行重试。此方法实现了指数退避算法，
     * 在每次重试之间增加等待时间，以避免对服务器造成过大压力。
     * 
     * 重试逻辑：
     * 1. 执行gRPC调用
     * 2. 检查调用状态
     * 3. 如果失败且满足重试条件，计算退避延迟
     * 4. 等待退避时间后重试
     * 5. 重复直到成功或达到最大重试次数/超时
     * 
     * 重试条件：
     * - 当前尝试次数小于最大重试次数
     * - 异常类型适合重试（由shouldRetry方法判断）
     * - 未超过截止时间
     * 
     * 退避算法：
     * 使用指数退避算法，每次重试的等待时间为：
     * delay = initial_delay * multiplier^(attempt-1)
     * 最大不超过max_delay
     * 
     * 使用场景：
     * - 网络不稳定环境下的调用
     * - 高并发场景下的调用
     * - 对可靠性要求高的调用
     * 
     * @param string $method 完整方法名，格式为"/服务名/方法名"
     * @param Message $request 请求消息
     * @param array $metadata 元数据
     * @param array $options 调用选项，包含重试和退避配置
     * @param int $deadline 截止时间（Unix时间戳）
     * @param int $attempt 当前尝试次数，默认为1
     * @return Message 响应消息
     * @throws \Throwable 当重试次数用尽或超过截止时间时抛出异常
     */
    protected function callWithRetry(string $method, Message $request, array $metadata, array $options, int $deadline, int $attempt = 1): Message
    {
        try {
            // 执行调用
            $call = $this->channel->call($method, $request, $metadata, $options);
            
            // 获取响应
            $response = $call->wait();
            
            // 获取状态
            $status = $call->getStatus();
            if ($status->code !== \Grpc\STATUS_OK) {
                throw new \RuntimeException("gRPC call failed: [{$status->code}] {$status->details}");
            }
            
            return $response;
        } catch (\Throwable $e) {
            // 检查是否需要重试
            if ($attempt < $options['retry'] && $this->shouldRetry($e) && time() < $deadline) {
                // 计算退避延迟
                $delay = $this->calculateBackoff($attempt, $options['backoff']);
                
                // 等待
                usleep($delay * 1000);
                
                // 重试
                return $this->callWithRetry($method, $request, $metadata, $options, $deadline, $attempt + 1);
            }
            
            // 不重试，抛出异常
            throw $e;
        }
    }
    
    /**
     * 判断是否应该重试
     * 
     * 根据异常类型判断是否应该进行重试。某些类型的错误不适合重试，
     * 例如认证错误、权限错误等，而网络错误、超时错误等适合重试。
     * 
     * 适合重试的异常类型：
     * - 网络连接错误
     * - 超时错误
     * - 服务器繁忙错误
     * - 临时服务不可用
     * 
     * 不适合重试的异常类型：
     * - 认证错误
     * - 权限错误
     * - 参数错误
     * - 方法不存在
     * 
     * 使用场景：
     * - 在重试逻辑中判断是否应该重试
     * - 避免无意义的重试
     * - 提高错误处理的精确性
     * 
     * @param \Throwable $e 异常对象
     * @return bool 是否应该重试
     */
    protected function shouldRetry(\Throwable $e): bool
    {
        // 这里可以根据异常类型判断是否应该重试
        // 例如，网络错误、超时等可以重试
        
        return true;
    }
    
    /**
     * 计算退避延迟
     * 
     * 使用指数退避算法计算重试前的等待时间。指数退避是一种在重试操作中
     * 逐渐增加等待时间的策略，可以避免对服务器造成过大压力。
     * 
     * 算法公式：
     * delay = initial_delay * multiplier^(attempt-1)
     * 
     * 参数说明：
     * - initial_delay: 初始延迟时间（毫秒）
     * - multiplier: 倍数因子，每次重试延迟时间乘以此因子
     * - max_delay: 最大延迟时间（毫秒），防止延迟时间过长
     * 
     * 示例：
     * initial_delay=100, multiplier=2, max_delay=10000
     * 第1次重试: 100 * 2^(1-1) = 100ms
     * 第2次重试: 100 * 2^(2-1) = 200ms
     * 第3次重试: 100 * 2^(3-1) = 400ms
     * 第4次重试: 100 * 2^(4-1) = 800ms
     * 第5次重试: 100 * 2^(5-1) = 1600ms
     * ...
     * 第7次重试: 100 * 2^(7-1) = 6400ms
     * 第8次重试: 100 * 2^(8-1) = 12800ms > 10000ms, 所以取10000ms
     * 
     * 使用场景：
     * - 在重试逻辑中计算等待时间
     * - 避免对服务器造成过大压力
     * - 提高重试的成功率
     * 
     * @param int $attempt 当前尝试次数
     * @param array $backoff 退避配置，包含initial、multiplier、max参数
     * @return int 延迟时间（毫秒）
     */
    protected function calculateBackoff(int $attempt, array $backoff): int
    {
        $delay = $backoff['initial'] * pow($backoff['multiplier'], $attempt - 1);
        return min($delay, $backoff['max']);
    }
    
    /**
     * 关闭客户端
     * 
     * 释放客户端资源，将连接返回到连接池。此方法不会真正关闭连接，
     * 而是将连接标记为可用，以便其他请求可以复用。这是连接池
     * 管理的一部分，可以提高性能。
     * 
     * 关闭流程：
     * 1. 检查通道是否存在
     * 2. 将连接返回到连接池
     * 3. 清空通道引用
     * 
     * 使用场景：
     * - 客户端不再使用时
     * - 应用关闭前
     * - 长时间运行的应用中定期释放资源
     * 
     * 使用示例：
     * ```php
     * $client = new GrpcClient('localhost:50051');
     * // 使用客户端...
     * 
     * // 关闭客户端
     * $client->close();
     * ```
     * 
     * @return void
     */
    public function close(): void
    {
        if (isset($this->channel)) {
            $this->connectionPool->releaseConnection($this->address, $this->channel);
            $this->channel = null;
        }
    }
    
    /**
     * 获取连接池统计信息
     * 
     * 获取连接池的统计信息，包括活跃连接数、空闲连接数、总连接数等。
     * 这些信息对于监控连接池状态和调优性能非常有用。
     * 
     * 统计信息包括：
     * - active_connections: 活跃连接数
     * - idle_connections: 空闲连接数
     * - total_connections: 总连接数
     * - connection_hits: 连接命中次数
     * - connection_misses: 连接未命中次数
     * 
     * 使用场景：
     * - 监控连接池状态
     * - 调优连接池配置
     * - 诊断连接问题
     * 
     * 使用示例：
     * ```php
     * $stats = GrpcClient::getConnectionPoolStats();
     * echo "活跃连接数: " . $stats['active_connections'] . "\n";
     * echo "空闲连接数: " . $stats['idle_connections'] . "\n";
     * ```
     * 
     * @return array 包含连接池统计信息的数组
     */
    public static function getConnectionPoolStats(): array
    {
        $connectionPool = ConnectionPool::getInstance();
        return $connectionPool->getStats();
    }
    
    /**
     * 获取序列化优化器统计信息
     * 
     * 获取序列化优化器的统计信息，包括序列化/反序列化次数、
     * 缓存命中率、平均耗时等。这些信息对于评估序列化性能
     * 和调优配置非常有用。
     * 
     * 统计信息包括：
     * - serialize_count: 序列化次数
     * - deserialize_count: 反序列化次数
     * - cache_hits: 缓存命中次数
     * - cache_misses: 缓存未命中次数
     * - avg_serialize_time: 平均序列化时间
     * - avg_deserialize_time: 平均反序列化时间
     * 
     * 使用场景：
     * - 监控序列化性能
     * - 调优序列化配置
     * - 诊断序列化问题
     * 
     * 使用示例：
     * ```php
     * $stats = GrpcClient::getSerializationStats();
     * echo "序列化次数: " . $stats['serialize_count'] . "\n";
     * echo "缓存命中率: " . ($stats['cache_hits'] / ($stats['cache_hits'] + $stats['cache_misses']) * 100) . "%\n";
     * ```
     * 
     * @return array 包含序列化优化器统计信息的数组
     */
    public static function getSerializationStats(): array
    {
        return SerializationOptimizer::getStats();
    }
    
    /**
     * 获取性能监控数据
     * 
     * 获取性能监控器收集的数据，包括请求次数、成功率、平均耗时、
     * 最大耗时、最小耗时等。这些数据对于评估gRPC调用的性能
     * 和识别性能瓶颈非常有用。
     * 
     * 性能数据包括：
     * - total_requests: 总请求数
     * - successful_requests: 成功请求数
     * - failed_requests: 失败请求数
     * - success_rate: 成功率
     * - avg_response_time: 平均响应时间
     * - max_response_time: 最大响应时间
     * - min_response_time: 最小响应时间
     * 
     * 使用场景：
     * - 监控gRPC调用性能
     * - 识别性能瓶颈
     * - 评估服务质量
     * 
     * 使用示例：
     * ```php
     * $data = GrpcClient::getPerformanceData();
     * echo "总请求数: " . $data['total_requests'] . "\n";
     * echo "成功率: " . ($data['success_rate'] * 100) . "%\n";
     * echo "平均响应时间: " . $data['avg_response_time'] . "ms\n";
     * ```
     * 
     * @return array 包含性能监控数据的数组
     */
    public static function getPerformanceData(): array
    {
        $performanceMonitor = PerformanceMonitor::getInstance();
        return $performanceMonitor->getPerformanceData();
    }
    
    /**
     * 获取请求历史
     * 
     * 获取最近的请求历史记录，包括请求时间、方法名、服务名、
     * 响应时间、状态等信息。可以选择只获取失败的请求，
     * 用于错误分析和问题排查。
     * 
     * 请求历史包括：
     * - request_id: 请求ID
     * - timestamp: 请求时间戳
     * - service: 服务名
     * - method: 方法名
     * - duration: 请求耗时（毫秒）
     * - status: 请求状态（成功/失败）
     * - error_message: 错误信息（如果有）
     * 
     * 使用场景：
     * - 分析最近的请求
     * - 排查失败请求的原因
     * - 监控请求模式
     * 
     * 使用示例：
     * ```php
     * // 获取最近100个请求
     * $history = GrpcClient::getRequestHistory(100);
     * foreach ($history as $request) {
     *     echo "{$request['service']}.{$request['method']}: {$request['duration']}ms\n";
     * }
     * 
     * // 只获取失败的请求
     * $failedRequests = GrpcClient::getRequestHistory(50, true);
     * foreach ($failedRequests as $request) {
     *     echo "失败: {$request['service']}.{$request['method']}: {$request['error_message']}\n";
     * }
     * ```
     * 
     * @param int $limit 限制数量，默认100
     * @param bool $onlyFailed 仅获取失败的请求，默认false
     * @return array 请求历史记录数组
     */
    public static function getRequestHistory(int $limit = 100, bool $onlyFailed = false): array
    {
        $performanceMonitor = PerformanceMonitor::getInstance();
        return $performanceMonitor->getRequestHistory($limit, $onlyFailed);
    }
    
    /**
     * 生成性能报告
     * 
     * 生成详细的性能报告，包括统计数据、图表和趋势分析。
     * 报告以文本格式返回，可以保存到文件或直接显示。
     * 
     * 报告内容包括：
     * - 总体统计信息
     * - 请求时间分布
     * - 成功率分析
     * - 热点服务和方法
     * - 错误分析
     * - 性能趋势
     * 
     * 使用场景：
     * - 定期性能评估
     * - 性能问题分析
     * - 服务质量报告
     * 
     * 使用示例：
     * ```php
     * // 生成并输出性能报告
     * $report = GrpcClient::generatePerformanceReport();
     * echo $report;
     * 
     * // 保存性能报告到文件
     * file_put_contents('performance_report.txt', $report);
     * ```
     * 
     * @return string 格式化的性能报告文本
     */
    public static function generatePerformanceReport(): string
    {
        $performanceMonitor = PerformanceMonitor::getInstance();
        return $performanceMonitor->generateReport();
    }
    
    /**
     * 启用性能监控
     * 
     * 启用性能监控功能，开始收集gRPC调用的性能数据。
     * 默认情况下，性能监控是启用的，但可以通过此方法
     * 显式启用，特别是在之前禁用后重新启用。
     * 
     * 使用场景：
     * - 应用启动时启用性能监控
     * - 诊断问题时临时启用
     * - 定期性能评估前启用
     * 
     * 使用示例：
     * ```php
     * // 启用性能监控
     * GrpcClient::enablePerformanceMonitoring();
     * 
     * // 执行一些gRPC调用...
     * 
     * // 获取性能数据
     * $data = GrpcClient::getPerformanceData();
     * ```
     * 
     * @return void
     */
    public static function enablePerformanceMonitoring(): void
    {
        $performanceMonitor = PerformanceMonitor::getInstance();
        $performanceMonitor->enable();
    }
    
    /**
     * 禁用性能监控
     * 
     * 禁用性能监控功能，停止收集gRPC调用的性能数据。
     * 禁用性能监控可以减少开销，适用于生产环境中
     * 不需要详细性能监控的场景。
     * 
     * 注意：
     * - 禁用后不会清除已收集的数据
     * - 可以通过enablePerformanceMonitoring重新启用
     * - 已收集的数据仍可通过相关方法获取
     * 
     * 使用场景：
     * - 生产环境中减少开销
     * - 性能测试时禁用监控
     * - 调试非性能问题时禁用
     * 
     * 使用示例：
     * ```php
     * // 禁用性能监控
     * GrpcClient::disablePerformanceMonitoring();
     * 
     * // 执行一些gRPC调用（不会被监控）...
     * 
     * // 重新启用性能监控
     * GrpcClient::enablePerformanceMonitoring();
     * ```
     * 
     * @return void
     */
    public static function disablePerformanceMonitoring(): void
    {
        $performanceMonitor = PerformanceMonitor::getInstance();
        $performanceMonitor->disable();
    }
    
    /**
     * 析构函数
     * 
     * 对象销毁时自动调用，确保客户端资源被正确释放。
     * 这是一个安全措施，即使用户忘记调用close()方法，
     * 也能保证连接被返回到连接池。
     * 
     * 注意：
     * - 析构函数的调用时机是不确定的
     * - 不应依赖析构函数来及时释放资源
     * - 建议显式调用close()方法
     * 
     * @return void
     */
    public function __destruct()
    {
        $this->close();
    }
}